﻿using System;
using AutoMapper;
using Crawler.Domain;
using Crawler.Domain.DataEntities;
using Crawler.Domain.DataEntities.Crawling;
using Crawler.Domain.DataEntities.Extracted;
using Crawler.Domain.Sources;
using Crawler.DomainServices.DataServices;
using Crawler.DomainServices.Pages;
using log4net;
using StructureMap;

namespace Crawler.ContentProcessors.Yify
{
	internal class YifyMoviePageContentProcessor : PageContentProcessor<MovieFile>
	{
		private static readonly ILog Logger = LogManager.GetLogger("AppLogger");
		private readonly ISourceContentRepository _contentRepository;
		private readonly IYifySubtitleProcessor _subtitleProcessor;

		public YifyMoviePageContentProcessor(IMoviesRepository moviesRepository,ISourceContentRepository contentRepository,
			IYifySubtitleProcessor subtitleProcessor)
		{
			MoviesRepository = moviesRepository;
			_contentRepository = contentRepository;
			_subtitleProcessor = subtitleProcessor;
		}

		private IMoviesRepository MoviesRepository { get; set; }

		public override PageSource ForSource
		{
			get { return PageSource.MovieYifyTorrent; }
		}

		protected override void Record(MovieFile data)
		{
			if (data == null) throw new ArgumentNullException("data");
			
			MoviesRepository.Save(data);
		}

		protected override MovieFile Parse<TSource>(TSource src)
		{
			var processableSource = src as MovieProcessableSource;
			if (processableSource == null) throw new InvalidOperationException();

			YifyMoviePage page = YifyMoviePage.FromHtml(processableSource);

			var result = Mapper.Map<MovieFile>(page);

			result.Torrents = new YifyTorrentFileLinkPage(processableSource.CrawlSessionId, page).GetTorrentFileUrls();
			
			   
			result.Movie = GetMovie(processableSource, page);

			ParseSubtitles(result);

			AddCrawlInfo(src as MovieProcessableSource, result);

			return result;
		}

		private void ParseSubtitles(MovieFile movieFile)
		{
			Movie movie = movieFile.Movie;
			movieFile.Subtitles = _subtitleProcessor.GetSubtitlesFor(movie.ImdbId);
			foreach (SubtitleFile s in movieFile.Subtitles)
			{
				s.SessionId = movie.SessionId;
			}
		}

		private Movie GetMovie(MovieProcessableSource processableSource, YifyMoviePage page)
		{
			Movie mov = MoviesRepository.GetMovieByTitle(page.Title, page.Year);
			if (mov == null)
			{
				RawPageCrawlInfo rawPage=  _contentRepository.GetProccessableContentByUrl(processableSource.CrawlSessionId, page.ImdbUrl);
				ImdbMoviePage imdbMoviePage;

				if (rawPage == null)
				{
					imdbMoviePage=ImdbMoviePage.FromUrl(page.ImdbUrl);
				}
				else
				{
					imdbMoviePage = ImdbMoviePage.From(rawPage);
				}
				imdbMoviePage.Load();
				mov = Mapper.Map<Movie>(imdbMoviePage);
				mov.FromUrl = imdbMoviePage.Url;
				mov.MPR = page.MPR;
				mov.SessionId = processableSource.CrawlSessionId;
				if (rawPage != null)
				{
					rawPage.Processed = true;
					rawPage.ProcessedDateTime=DateTime.UtcNow;
					_contentRepository.Save(rawPage);
				}
			}
			return mov;
		}

		private void AddCrawlInfo(MovieProcessableSource src, CrawlInfo crawlInfo)
		{
			crawlInfo.FromUrl = src.AbsoluteUri;
			crawlInfo.UtcCrawled = DateTime.UtcNow;
			crawlInfo.SessionId = src.CrawlSessionId;
		}

		protected override bool MustProcess(string url)
		{
			return url.ToLower().StartsWith("http://www.yify-torrent.org/movie/") &&
			       MoviesRepository.CountFileByUrl(url) == 0;
		}
	}
}